package com.ng.framework.view.desktop.table;

import java.awt.Component;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.ParsePosition;

import javax.swing.DefaultCellEditor;
import javax.swing.JFormattedTextField;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.text.NumberFormatter;

import org.apache.commons.lang.StringUtils;

public class NGNumberCellEditor<T extends Number> extends DefaultCellEditor {

	private static final long serialVersionUID = -4088856138713070650L;

	private Class<T> clazz;
	private NumberFormat numberFormat;

	public NGNumberCellEditor(Class<T> clazz, NumberFormat numberFormat) {
		super(new JFormattedTextField());

		this.clazz = clazz;
		this.numberFormat = numberFormat;
	}

	@Override
	public Component getTableCellEditorComponent(JTable table, Object value,
			boolean isSelected, int row, int column) {
		final JFormattedTextField editor = (JFormattedTextField) super
				.getTableCellEditorComponent(table, value, isSelected, row,
						column);

		if (value instanceof Number) {
//			Locale locale = Locale.getDefault();

//			NumberFormat numberFormat = NumberFormat.getInstance(locale);
//			numberFormat.setMaximumFractionDigits(2);
//			numberFormat.setMinimumFractionDigits(2);
//			numberFormat.setMinimumIntegerDigits(1);

			editor.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(
					new NumberFormatter(numberFormat)));

			editor.setHorizontalAlignment(SwingConstants.RIGHT);
			editor.setValue(value);

			editor.selectAll();

			SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					editor.requestFocus();

					SwingUtilities.invokeLater(new Runnable() {
						public void run() {
							editor.setCaretPosition(editor.getText().length());
						}
					});
				}
			});
		}
		return editor;
	}

	@Override
	public boolean stopCellEditing() {
		try {
			this.getCellEditorValue();
			return super.stopCellEditing();
		} catch (Exception ex) {
			ex.printStackTrace();
			return false;
		}

	}

	@Override
	public Object getCellEditorValue() {
		Object value = null;

		String s = (String) super.getCellEditorValue();
		if (!StringUtils.isEmpty(s)) {
			try {
				ParsePosition parsePosition = new ParsePosition(0);
				Number number = NumberFormat.getInstance().parse(s,
						parsePosition);
				if (parsePosition.getIndex() != s.length()) {
					throw new ParseException("parsing incomplete",
							parsePosition.getIndex());
				}

				value = this.toExcpectedType(number);
			} catch (ParseException pex) {
				throw new RuntimeException(pex);
			}
		}

		return value;
	}

	private Number toExcpectedType(Number number) {
		Number expectedTypeNumber = null;

		if (this.clazz == Byte.class) {
			expectedTypeNumber = new Byte(number.byteValue());
		} else if (this.clazz == Short.class) {
			expectedTypeNumber = new Short(number.shortValue());
		} else if (this.clazz == Integer.class) {
			expectedTypeNumber = new Integer(number.intValue());
		} else if (this.clazz == Long.class) {
			expectedTypeNumber = new Long(number.longValue());
		} else if (this.clazz == Float.class) {
			expectedTypeNumber = new Float(number.floatValue());
		} else if (this.clazz == Double.class) {
			expectedTypeNumber = new Double(number.doubleValue());
		}

		return expectedTypeNumber;
	}

}
